// Copyright (C) 1953-2022 NUDT
// Verilog module name - packet_abstract_extract
// Version: V4.0.20221216
// Created:
//         by - fenglin
////////////////////////////////////////////////////////////////////////////
// Description:
//         packet_abstract_extract
///////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ps

module packet_abstract_extract#(parameter port_type = 5'h00)
(
		i_clk,
		i_rst_n,
	//Network input top module
		i_gmii_clk,
		i_gmii_en,
		iv_gmii_data,
		i_gmii_er,
		iv_mirror_mode,
		iv_syn_clk,
		i_descriptor_ack,
		ov_pkt_abstract,		
		o_pkt_abstract_wr   
);

input					i_clk;
input           		i_rst_n;
input					i_gmii_clk;
input 					i_gmii_en;
input 			[7:0]	iv_gmii_data;
input					i_gmii_er;
input 			[1:0]	iv_mirror_mode;
input 			[79:0]	iv_syn_clk;
input					i_descriptor_ack;
output	reg		[127:0]	ov_pkt_abstract;
output	reg		      	o_pkt_abstract_wr;


reg		        [127:0]	rv_pkt_data;
reg 			[79:0]	rv_syn_clk;
reg 					rdreq;
wire			[7:0]	dcfifo_data;
wire					rdempty;
reg 			[10:0]	tick_count;
reg 			[7:0]	rv_ethtype;
reg				[13:0]	flowid_pre_reg;

reg				[3:0]	pug_state;
localparam				idle				= 4'd0,
						delay		        = 4'd1,
						wait1			    = 4'd2,
						wait2			    = 4'd3,						
						read_start			= 4'd4,
						read_ethtype		= 4'd5,				
						read_flowid		    = 4'd6,						
						pulse_generate_s	= 4'd7,
						read_rest			= 4'd8;
						
always@ (posedge i_clk or negedge i_rst_n)begin
	if(!i_rst_n) begin
		rv_pkt_data <= 128'b0;
	end
	else begin
		rv_pkt_data <= {rv_pkt_data[119:0],dcfifo_data};
	end
end	
	

always@ (posedge i_clk or negedge i_rst_n)begin
	if(!i_rst_n) begin
		tick_count			<= 11'b0;
		rdreq				<= 1'b0;
		flowid_pre_reg		<= 14'b0;
		rv_syn_clk			<= 64'b0;
		rv_ethtype          <= 8'b0;
		pug_state			<= idle;			
	end
	else begin
		case (pug_state)
			idle: begin
				tick_count	<= 11'b0;
				if (!rdempty) begin
					pug_state	<= delay;
				end
				else begin
					pug_state	<= idle;
				end
			end
            delay:begin
                pug_state <= wait1;            
            end 
            wait1:begin
                rdreq     <= 1'b1;
                pug_state <= wait2;
            end  	
            wait2:begin
                rdreq     <= 1'b1;
                pug_state <= read_start;
            end  			
			read_start: begin
			    rdreq     <= 1'b1;
				if (dcfifo_data == 8'h55) begin
					tick_count	<= 11'b0;
					pug_state	<= read_start;
				end	
				else if (dcfifo_data == 8'hd5) begin
					rv_syn_clk	<= iv_syn_clk;
					tick_count	<= tick_count + 1'b1;
					pug_state	<= read_ethtype;
				end	
				else begin
					tick_count	<= 11'b0;
					pug_state	<= read_rest;
				end
			end		
			read_ethtype: begin
			    rdreq           <= 1'b1;
				tick_count		<= tick_count + 1'b1;
				if (tick_count == 11'd13)begin
					rv_ethtype  <= dcfifo_data;
					pug_state	<= read_ethtype;								
				end
				else if (tick_count == 11'd14) begin
					if({rv_ethtype,dcfifo_data}==16'h8100)begin
						pug_state	<= read_flowid;
					end
					else begin
						pug_state	<= read_rest;
					end								
				end				
				else begin	
					pug_state	<= read_ethtype;				
				end						
			end		
			read_flowid: begin
			    rdreq           <= 1'b1;
				tick_count		<= tick_count + 1'b1;
				if (tick_count == 11'd15) begin	
					flowid_pre_reg[13:8]<= dcfifo_data[5:0];
					pug_state	    <= read_flowid;	
				end
				else if (tick_count == 11'd16) begin	
					flowid_pre_reg[7:0]<= dcfifo_data;
					pug_state	    <= read_flowid;	
				end	
				else if (tick_count == 11'd17)begin	
					pug_state	    <= read_rest;	

				end
				else begin
					pug_state	<= read_rest;
				end							
			end
			read_rest: begin
				if (!rdempty) begin
					tick_count		<= tick_count + 1'b1;
					pug_state	    <= read_rest;
				end
				else begin
					tick_count		<= 11'b0;
					rv_ethtype      <= 8'b0;
					flowid_pre_reg	<= 14'b0;
					rdreq			<= 1'b0;
					pug_state	    <= idle;
				end
			end
		endcase
	end
end
reg [1:0]           pae_state;
localparam  idle_s          = 2'b00,
            wait_des_ack_s  = 2'b10;
always@ (posedge i_clk or negedge i_rst_n)begin
	if(!i_rst_n) begin
		ov_pkt_abstract    <= 128'b0;	
		o_pkt_abstract_wr  <= 1'b0;	
		pae_state       <= idle_s;		
	end
	else begin
		case(pae_state)
            idle_s:begin		
				if(iv_mirror_mode==2'b01)begin
					if(tick_count==11'd17)begin
						if(rv_pkt_data[31:16]==16'h8100)begin
							ov_pkt_abstract[127:48]  <= rv_syn_clk;	
							ov_pkt_abstract[47:32]   <= {1'd0,rv_pkt_data[14:0]};	
							ov_pkt_abstract[31:16]   <= rv_pkt_data[31:16];
							ov_pkt_abstract[15:0]    <= {11'd0,port_type};
							o_pkt_abstract_wr  <= 1'b1;	
							pae_state          <= wait_des_ack_s;	
						end					
						else begin 
							ov_pkt_abstract    <= 128'b0;	
							o_pkt_abstract_wr  <= 1'b0;	
							pae_state       <= idle_s;
							
						end
					end
					else begin
						ov_pkt_abstract    <= 128'b0;	
						o_pkt_abstract_wr  <= 1'b0;	
						pae_state       <= idle_s;						
					end
				end
				else if(iv_mirror_mode==2'b11)begin
					if(tick_count==11'd17)begin
						if(rv_pkt_data[31:16]==16'h8100)begin
							ov_pkt_abstract[127:48]  <= rv_syn_clk;	
							ov_pkt_abstract[47:32]   <= {1'd0,rv_pkt_data[14:0]};
							ov_pkt_abstract[31:16]   <= rv_pkt_data[31:16];
							ov_pkt_abstract[15:0]    <= {11'd0,port_type};
							o_pkt_abstract_wr  <= 1'b1;	
							pae_state          <= wait_des_ack_s;	
						end					
						else begin 
							ov_pkt_abstract[127:16]  <= rv_pkt_data[127:16];	
							ov_pkt_abstract[15:0]    <= {11'd0,port_type};
							o_pkt_abstract_wr  <= 1'b1;	
							pae_state          <= wait_des_ack_s;	
						end
					end
					else begin
						ov_pkt_abstract    <= 128'b0;	
						o_pkt_abstract_wr  <= 1'b0;	
						pae_state          <= idle_s;						
					end		
				end
				else begin
					ov_pkt_abstract    <= 128'b0;	
					o_pkt_abstract_wr  <= 1'b0;	
					pae_state          <= idle_s;					
				end
			end
            wait_des_ack_s:begin          
                if(i_descriptor_ack == 1'b1) begin
					ov_pkt_abstract     <= 128'b0;	
					o_pkt_abstract_wr   <= 1'b0;	
					pae_state           <= idle_s;	
                    end
                else begin
                    ov_pkt_abstract     <= ov_pkt_abstract ; 
                    o_pkt_abstract_wr   <= o_pkt_abstract_wr;
                    pae_state           <= wait_des_ack_s;
                    end
                
                end
            default:begin
				ov_pkt_abstract     <= 128'b0;	
				o_pkt_abstract_wr   <= 1'b0;	
				pae_state           <= idle_s;	
            end
        endcase
    end			
end	
	
ASFIFO_8_16  ASFIFO_8_16_inst
(        
    .wr_aclr(~i_rst_n),                                         //Reset the all signal
    .rd_aclr(~i_rst_n),
    .data   (iv_gmii_data),                                         //The Inport of data 
    .rdreq  (rdreq),                                           //active-high
    .wrclk  (i_gmii_clk),                                          //ASYNC WriteClk(), SYNC use wrclk
    .rdclk  (i_clk),                                         //ASYNC WriteClk(), SYNC use wrclk  
    .wrreq  (i_gmii_en),                                          //active-high
    .q      (dcfifo_data),                                             //The output of data
    .wrfull (fifo_wrfull),                                           //Write domain full 
    .wralfull(),                                        //Write domain almost-full
    .wrempty(),                                     //Write domain empty
    .wralempty(),                                       //Write domain almost-full  
    .rdfull (),                                          //Read domain full
    .rdalfull(),                                        //Read domain almost-full   
    .rdempty(rdempty),                                        //Read domain empty
    .rdalempty(),                                       //Read domain almost-empty
    .wrusedw(),                                     //Write-usedword
    .rdusedw()          
    );	
	
endmodule